/*
银行取款系统
在这个例子中，多个客户线程尝试从同一个银行账户中取款。银行账户的余额是一个共享资源，因此需要用互斥锁来保护，
以防止多个线程同时访问导致的数据竞争。同时，我们使用一个无名信号量来模拟银行柜员的数量限制，
即同一时间最多只能有几个客户同时进行取款操作。
 */
#include <head.h>

int num = 100; // 银行现金

// 定义信号量
sem_t sem;

pthread_mutex_t mutex;


void *sem_func(void *val); // 取钱

int main(int argc, char const *argv[])
{
    pthread_t Tid[5];
    pthread_mutex_init(&mutex, NULL);

    int Id_arr[5] = {1, 2, 3, 4, 5};
    sem_init(&sem, 0, 2); // 两个柜台
    int __errnum;
    for (int i = 0; i < 5; i++)
    {

        if (0 != (__errnum = pthread_create(&Tid[i], NULL, sem_func, (void *)&Id_arr[i])))
        {
            printf("pthread_create error: %d %s\n", __errnum, strerror(__errnum));
        }
        // 重置错误码 == 重置 系统中的 error 的值 perror 是可以直接获取的

        // 返回错误码 == 当函数出错时 返回错误码编号 strerror
    }
    // 回收线程
    for (int i = 0; i < 5; i++)
    {
        pthread_join(Tid[i], NULL);
    }

    // 销毁信号
    sem_destroy(&sem);
    pthread_mutex_destroy(&mutex);
    return 0;
}

void *sem_func(void *val)
{
    int id = *(int *)val;

    // pthread_mutex_lock(&mutex);
    printf("第%d个人等待取钱 .....\n", id);

    // P操作
    sem_wait(&sem);
    printf("第%d个人开始取钱 .....\n", id);
    sleep(2);
    printf("第%d个人取钱成功 ===>\n", id);

    num--;
    // V操作
    sem_post(&sem);

    printf("银行剩余现金余额:%d \n", num);

    // pthread_mutex_unlock(&mutex);
    sleep(1);
}
